/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package casino;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 *
 * @author amaghfur
 */
public class Simulator {
    
    /** initial duration of each cycle measured by the number of cycles played in a session */
    private final int initDuration = 250;
    /** initial stake */
    private Rational initStake = new Rational(500);
    /** number of game cycles to simulate */
    private int samples = 50;
    /** a sample of lengths of time the player remained in the game */
    private List<Integer> durations = new ArrayList<>();
    /** a sample of maximum stake the player had in the game */
    private List<Integer> maxima = new ArrayList<>();
    /** the player */
    private Player player;
    /** the game */
    private Game game;
    
    /**
     * Class constructor to run a simulation of the specified game played by the
     * specified player.
     * 
     * @param gameToPlay    game played
     * @param playerOfGame  player playing
     */
    public Simulator(Game gameToPlay, Player playerOfGame) {
        game = gameToPlay;
        player = playerOfGame;
    }
    
    /**
     * Getter for durations.
     * 
     * @return  durations 
     */
    public List<Integer> getDurations() {
        return durations;
    }
    
    /**
     * Getter for maxima.
     * 
     * @return  maxima 
     */
    public List<Integer> getMaxima() {
        return maxima;
    }
    
    /**
     * Setter for initStake
     * 
     * @param newInitStake
     */
    public void setInitStake(Rational newInitStake) {
    	initStake = newInitStake;
    }
    
    /**
     * Executes a single game session of a player and return a list detailing the changes
     * to the player's stake.
     * 
     * @return  a list detailing the stake changes throughout the session
     */
    public List<Integer> session() {
        System.out.println("start session");
        player.setStake(initStake);
        player.setRounds(initDuration);
        player.reset(); // reset the player's state before each new session
        List<Integer> stakeList = new ArrayList<>();
        while(player.playing() == true) {
            game.cycle(player);
            stakeList.add(player.getStake().convertToInteger());
        }
        return stakeList;
    }
    
    /**
     * Executes the number of game sessions in samples and compile the durations and maxima
     * from all of them.
     */
    public void gather() {
        for(int cnt=1; cnt<=samples; cnt++) {
            List<Integer> sessionList = session();
            durations.add(sessionList.size());
            maxima.add((int)Collections.max(sessionList));
        }
    }
    
    /**
     * Print the raw results of the gathered durations and maxima.
     */
    public void printRawResults() {
        System.out.println("DURATIONS - raw results");
        for(Integer d : durations) {
            System.out.println(d.toString());
        }
        
        System.out.println("MAXIMA - raw results");
        for(Integer m : maxima) {
            System.out.println(m.toString());
        }    
    }
    
    /**
     * Print the mean and standard deviation of the gathered durations and maxima.
     */
    public void printSummaryResults() {
        // print durations mean and stdev
        System.out.println("DURATIONS");
        double durationsMean = InterStatistics.mean(durations);
        double durationsStdev = InterStatistics.stdev(durations);
        System.out.println("mean = " + String.valueOf(durationsMean));
        System.out.println("stdev = " + String.valueOf(durationsStdev));
        // print maxima mean and stdev
        System.out.println("MAXIMA");
        double maximaMean = InterStatistics.mean(maxima);
        double maximaStdev = InterStatistics.stdev(maxima);
        System.out.println("mean = " + String.valueOf(maximaMean));
        System.out.println("stdev = " + String.valueOf(maximaStdev));
    }
    
}
